package org.truenewx.tnxjee.webmvc.response.exception.resolver;

import javax.annotation.*;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.ModelAndView;
import org.truenewx.tnxjee.service.exception.*;
import org.truenewx.tnxjee.webmvc.security.web.RestResponseResultDecider;

/**
 * 可解决异常处理至响应体中的解决器
 *
 * @author jianglei
 */
public class BodyResolvableExceptionResolver extends ResolvableExceptionResolver {

    @Autowired(required = false)
    private RestResponseResultDecider restResponseResultDecider;

    public BodyResolvableExceptionResolver() {
        setOrder(Ordered.HIGHEST_PRECEDENCE + 2);
    }

    @Override
    protected boolean supports(HttpServletRequest request, Object handler) {
        return this.handlerMethodMapping.isRestRequest(request, handler);
    }

    @Override
    protected ModelAndView getResult(HttpServletRequest request, HttpServletResponse response,
            @Nullable Object handler, ResolvableException re) {
        response.setStatus(getResponseStatus(request, re));
        return new ModelAndView();
    }

    protected int getResponseStatus(HttpServletRequest request, ResolvableException re) {
        int status = getDefaultResponseStatus(re);
        if (this.restResponseResultDecider != null && this.restResponseResultDecider.supports(request)) {
            request.setAttribute(RestResponseResultDecider.ATTR_DEFAULT_STATUS, status);
            status = this.restResponseResultDecider.getResolvableExceptionStatus(re);
        }
        return status;
    }

    private int getDefaultResponseStatus(ResolvableException re) {
        if (re instanceof FormatException) {
            return HttpServletResponse.SC_BAD_REQUEST;
        } else if (re instanceof MultiException me) {
            for (SingleException se : me) {
                if (se instanceof FormatException) {
                    return HttpServletResponse.SC_BAD_REQUEST;
                }
            }
        }
        return HttpServletResponse.SC_OK;
    }

}
